:- module(form_page,
	[
	    generate_form_page/4,
	    generate_selected_termnames/1
	], [functions, pillow, assertions,regtypes,basicmodes]).
:- function(arith(false)).

:- use_module(library(aggregates), [setof/3, (^)/2, findall/3]).
:- use_module(library(lists), [append/3, length/2]).
:- use_module(library(between), [between/3]).
:- use_module(library('pillow/pillow_types')).


:- use_module(portalfiles(web_utils), [generate_box/2]).
:- use_module(portalfiles(standard_page), [standard_page/5]).
:- use_module(search(utils), [log_message/1, remove_dir/2]).
:- use_module(search(results_page), [results_page/3]).
:- use_module(search(error_page), [error_page/2]).
:- use_module(search(match_interface), [values/1, id/1, results/1]).

:- include(which_match_to_use).

:- comment(module,"This module generates the initial search form, used
	to perform queries. The initial search form must be generated
	dynamically, as it depends on the description terms stored in
	the Amos database.").

% This page generates the initial form page
% Variable Body holds the central text of the page
% SB1 is the topmost SideBox, which depends of the page.
% The rest of the layour and contents is fixed.

:- true pred generate_form_page(in(Values), in(PageId), in(Results),
   go(HTML)) :: values * id * results * html_term

# "Generates in @var{HTML} the code of the main search page, using
   @var{Values} as the values to fill in the fields of the search
   form. This HTML page may contain results of previous queries, that
   can be specified in @var{Results}, if it is available.".

generate_form_page(Values, PageId, Results, HTML):-
        generate_box(box_search, SB1),
        log_message('Search box generated'),
        standard_page(all, "Search the AMOS Database",
                       SB1,
                       Body,
                       HTML),
        log_message('Search page skeleton generated'),
        form_page_body(Values, PageId, Results, Body),
        log_message('Search page body generated').

form_page_body(Values, PageId, Results, Body):-
        Values = values(Terms, Ini, NumOfMatches, Timeout, SortMethod, Mode, InP, ExP),
	SortMethod = key_weights(
	       WPackageNumber,
	       WUnsatisfiedDeps,
	       WTighterAssemblies,
	       WCapabilities,
	       WBestCapabilitiesRatio),
	Mode = gen(LevelPrec, LevelPost),
        ( % Avoid failures if empty database
            setof(W, get_readable_term_name(W), Sort)
        ;
            Sort = []
        ), !,
        number_of_columns(NC),
        generate_pd_menus(Sort, NC, TermDescRows),
        atom_number(NCAt, NC),
        TermDesc=[
                     begin(table, [cols=NCAt, border="box"]), nl,
                     begin(tbody, [valign="baseline", align="left"]),nl,
                     TermDescRows, nl,
                     end(tbody), nl,
                     end(table), nl
                 ],		

	( Results = input_errors(InputErrors) ->
	    error_page(InputErrors, ResultsHTML)
	; Results = results(_, _, _) ->
	    ( results_page(Values, Results, ResultsHTML) ->
	        true
	    ; ResultsHTML = 'Results failed!' % todo: should not happen!
	    )
	; Results = match_failed -> % todo: should not happen!
	    ResultsHTML = 'Match failed!'
	; Results = no_results ->
	    ResultsHTML = []
	),
	TableBGColor = "#e9e8e4",
	Body = [
        start_form,
        begin(table, [cols="2",width="100%"]), nl,
          begin(tbody), nl,
          begin(tr),
                                                % Required terms
          td([valign="top", colspan="1", 
              style="padding:4px", bgcolor=TableBGColor], [
%             b("Required terms: "),
              input(submit, 
                   [value="Search these terms &rArr;",
                    style="width:100%",
                    align="right"
                    ])
%             input(name, [name=search_terms,size=55, value = Terms]),
%             input(submit, [name = revert, value = "Clear"])
                                                               ]),
          td([valign="top", colspan="1", style="padding:4px", 
              bgcolor=TableBGColor], [
%             b("Required terms: "),
%             input(submit, [value="Search these terms:",style="width:100%"]),
              input(name, [name=search_terms,size=52, value = Terms]),
              " ",
              input(submit, [name = revert, value = "Clear"])
                                                               ]),
          end(tr),

          begin(tr),
                                                % Term list
         td([valign="top", style="padding:4px",bgcolor=TableBGColor],
            [
               b(input(submit,
                       [name=add_to_search, value="Add to search",
                        style="width:100%", bgcolor=TableBGColor])), \\,
%                font([], b(["Select terms from list:"])), \\,
               TermDesc,
               b(input(submit,
                      [name=term_description_page,value="Description of terms",
                       style="width:100%"]))]), nl,
                                                % Options
            td([valign="top", style="padding:4px",
                width="100%", bgcolor=TableBGColor, align=left],
                [p([], [
                    b("Prefer assemblies"), " with ",
                    ~html_select( wpackagenumber, WPackageNumber,
				                    [ (-2)="very few",
						       (-1)="few",
							0="any number of",
							1="a few",
							2="many"
						    ]
						  ),
				      " packages, ",
                    ~html_select(wunsatisfieddeps, WUnsatisfiedDeps,
				                  [
						    (-2)="very few",
						    (-1)="few",
						       0="any number of"
						  ]
						  ),
				      " unsatisfied requirements, ",
                    ~html_select(wtighterassemblies, WTighterAssemblies,
				                  [
						    (-2)="very few",
						    (-1)="few",
						     0="any number of"
						  ]
						  ),
				       " auxiliary requirements, ",
                    ~html_select(wcapabilities, WCapabilities,
				                  [
						    (-2)="very few",
						    (-1)="few",
						     0="any number of",
						     1="a few",
						     2="many"
						  ]
						  ),
					" capabilities and ",
                    ~html_select(wbestcapabilitiesratio,WBestCapabilitiesRatio,
					            [
						      (-2)="a very small",
						      (-1)="a small",
						       0="any",
						       1="a large",
						       2="a very large"
						    ]
						    ),
					" ratio of fulfilled capabilities. ",
                   \\, 
                   b("Stop"), " after at most ",
                    ~html_select(timeout, Timeout,
					            [
						       1="1",
						       5="5",
						       10="10",
						       30="30",
						       60="60"
						    ]
						    ),
					" seconds."]
			    ),
                p([], [" Use at most ",
		   ~html_select(search_levelpost, LevelPost,
                                [0="0", 1="1", 2="2", 3="3", 4="4", 5="5"]),
		   span([style='color:#04f'], b(" safe ")), 
                   "and ",
		   ~html_select(search_levelprec, LevelPrec,
                               [0="0", 1="1", 2="2", 3="3", 4="4", 5="5"]),
                   span([style='color:#f40'], b(" unsafe ")), 
                   "generalizations."]),

                p([], [
                  begin(table, [cols="2",width="100%"]), nl,
                  begin(tbody),
                  begin(tr),
                  td([colspan=2],
                  font([],b("Enter here the names of packages to be"))),
                  end(tr),
                  begin(tr),
		  td([],font([],b("Included: "))),
                  td([], input(name, 
                      [name=include_pkgs, size=50, value=InP])),
                  end(tr),
                  begin(tr),
		  td([],font([],b("Excluded: "))),
		  td([],input(name, [name=exclude_pkgs, size=50, value=ExP])),
                  end(tr),
                  end(tbody),
                  end(table)
		  ])]),
	      end(tr),
              end(tbody),
              end(table),

		   input(hidden, [name=ini, value=Ini]),
		   input(hidden, [name=num_matches, value=NumOfMatches]),

		   \\,

		   % todo: put label to options, put label to term list
		   ResultsHTML,

                 %% Here: the form is filled in for the next page
                   input(hidden, [name=page_id, value=PageId]),
                   input(hidden, [name=search_summary, value="yes"]),
                   end_form
             ].



number_of_columns(1).


%%  get_readable_term_name('Name to be generated').

get_readable_term_name(Name):-
        term_desc(ThisTerm, _Desc, _Gen),
        name(ThisTerm, ThisTermStr),
        remove_dir(ThisTermStr, Name).

generate_pd_menus(Terms, NumOfCols, [begin(tr), TableRows, end(tr)]):-
        length(Terms, HowMany),
        PerColumn is 1 + (HowMany // NumOfCols),
        make_columns(Terms, 1, PerColumn, TableRows).


make_columns([], _, _, []):- !.
make_columns(AllTerms, ColumnNumber, PerColumn,
             [begin(td), nl,
              menu(ThisColumnName, [multiple, size="11"], ThisColumn),
              nl, end(td)|RestR]):-
           give_me_column_name(ColumnNumber, ThisColumnName),
        (
            length(ThisColumn, PerColumn),
            append(ThisColumn, RestTerms, AllTerms) ->
            true
        ;
            RestTerms = [],
            ThisColumn = AllTerms
        ),
        NextColumnNumber is ColumnNumber + 1,
        make_columns(RestTerms, NextColumnNumber, PerColumn, RestR).

give_me_column_name(Num, Name):-
	atom_number(AtColNum, Num),
	base_selection_column_name(BCN),
	atom_concat(BCN, AtColNum, Name).


base_selection_column_name(selection_column_).

:- pred generate_selected_termnames(go(TermNames2Add)) :: list(atm)

# "Obtains the names of the selection lists of description terms in
  the search form page.".

generate_selected_termnames(TermNames2Add) :-
	number_of_columns(NC),
        findall(At,
        (between(1, NC, ColNum),
                 give_me_column_name(ColNum, At)),
                TermNames2Add).

html_select(Name, Value, Options) :=
	select([name=Name], ~html_select__2(Options, Value)).

html_select__2([], _) := [].
html_select__2([Value=Text|Options], Value0) :=
	[option([value=Value|Atts], Text)| ~html_select__2(Options, Value0)] :-
        ( Value == Value0 ->
	    Atts = [selected]
	; Atts = []
	).


